dnl
dnl Copyright (C) 2008,2009,2010  Paulo Cesar Pereira de Andrade.
dnl
dnl This is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation; either version 3 of the License, or
dnl (at your option) any later version.
dnl
dnl This software is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dnl GNU General Public License for more details.
dnl
dnl Authors:
dnl	Paulo Cesar Pereira de Andrade
dnl

dnl  Process this file with autoconf to create configure.

AC_PREREQ([2.57])
AC_INIT(exl, [0.0.1], , exl)
AC_CONFIG_SRCDIR([Makefile.am])
AM_INIT_AUTOMAKE([dist-bzip2])
AC_CONFIG_MACRO_DIR([m4])

AC_CANONICAL_TARGET
AM_CONFIG_HEADER(config.h)

AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LIBTOOL

AC_CHECK_LIB(gmp, __gmpz_init, ,
	[AC_MSG_ERROR([GNU MP not found, see http://gmplib.org/])])

AC_CHECK_LIB(mpfr, mpfr_init, ,
	[AC_MSG_ERROR([MPFR not found, see http://www.mpfr.org/])])

AC_CHECK_LIB(mpc, mpc_add, ,
	[AC_MSG_ERROR([MPC not found, see http://www.multiprecision.org/])])

AC_CHECK_HEADER([complex.h],
	[AC_DEFINE([HAVE_COMPLEX_H], 1,
		[Define to 1 if you have the <complex.h> header file.])],
	[AC_MSG_ERROR([C99 complex numbers support required])])

dnl Check for a C99 compliant cproj implementation
dnl http://sourceware.org/bugzilla/show_bug.cgi?id=10401
dnl (bug marked as fixed in git)
AC_MSG_CHECKING([for functional c99 cproj])
c99_proj_ok=yes
save_LIBS=$LIBS
LIBS="$LIBS -lm"
AC_RUN_IFELSE([AC_LANG_PROGRAM([#include <complex.h>],
		[return cproj(0.5+0.5*I) == 0.5+0.5*I;])],
	[c99_proj_ok=no],
	AC_DEFINE([HAVE_C99_CPROJ], 1,
		[Define to 1 if cproj is c99 compliant.]),
	[c99_proj_ok="not testing when cross compiling"])
AC_MSG_RESULT([$c99_proj_ok])
LIBS=$save_LIBS

AC_MSG_CHECKING([for clog10 support])
clog10_ok=yes
save_LIBS=$LIBS
LIBS="$LIBS -lm"
AC_TRY_LINK([#include <complex.h>],
		[return = clog10(1.0);],
	AC_DEFINE([HAVE_CLOG10], 1,
		[Define to 1 if clog10 is available.]),
	[clog10_ok=no])
AC_MSG_RESULT([$clog10_ok])
LIBS=$save_LIBS

AC_MSG_CHECKING([for sincos support])
sincos_ok=yes
save_LIBS=$LIBS
LIBS="$LIBS -lm"
AC_TRY_LINK([double a, b;],
		[sincos(1.0, &a, &b);],
	AC_DEFINE([HAVE_SINCOS], 1,
		[Define to 1 if sincos is available.]),
	[sincos_ok=no])
AC_MSG_RESULT([$sincos_ok])
LIBS=$save_LIBS

AC_MSG_CHECKING([for isinff support])
isinff_ok=yes
save_LIBS=$LIBS
LIBS="$LIBS -lm"
AC_TRY_LINK([int i; float a = 1.0;],
		[i = isinff(a);],
	AC_DEFINE([HAVE_ISINFF], 1,
		[Define to 1 if isinff is available.]),
	[isinff_ok=no])
AC_MSG_RESULT([$isinff_ok])
LIBS=$save_LIBS

dnl TSL is used everywhere in the sources, so for now add
dnl only a quick hack to disable thread support if the __thread
dnl keyword does not work.
dnl Alternative should be to pass a ethread_t pointer everywhere,
dnl and use pthread_{g,s}etspecific where not possible, should
dnl work on signal handlers.
AC_MSG_CHECKING([for TLS support])
tls_ok=yes
save_CFLAGS=$CFLAGS
CFLAGS="-pthread"
AC_TRY_LINK([__thread void *tls_var;],
		[tls_var = malloc(1024);],
	AC_DEFINE([HAVE_THREAD], 1,
		[Define to 1 if __thread is available.]),
	[tls_ok=no])
AC_MSG_RESULT([$tls_ok])
CFLAGS=$save_CFLAGS
AM_CONDITIONAL(WITH_THREAD, [test "x$tls_ok" != "xno"])
if test "x$tls_ok" != "xno"; then
    EXL_CFLAGS="$EXL_CFLAGS -pthread"
fi

dnl Debug/production build enable/disable
AC_ARG_WITH(debug,
	      AS_HELP_STRING([--with-debug[=TYPE]],
			     [Enable debug code, consistency checking, and assertions (known values: auto (default), yes, no, mudflap)]),
	      [DEBUG=$withval], [DEBUG=auto])
if test "x$DEBUG" != "xno"; then
    DEBUG_CFLAGS="-DDEBUG=1"
    if test "x$DEBUG" = xmudflap; then
	DEBUG_CFLAGS="$DEBUG_CFLAGS -fmudflapth -lmudflapth"
    fi
else
    DEBUG_CFLAGS="-DNDEBUG=1"
fi
AC_SUBST([DEBUG_CFLAGS])

AC_ARG_ENABLE(jit,
	      AS_HELP_STRING([--enable-jit],
			     [Enable jit vm]),
	      [JITVM=$enableval], [JITVM=auto])

if test "x$JITVM" = "xauto"; then
    # if supported
    case "$target_cpu" in
	i?86|x86_64|mipsel|arm*|powerpc)	;;
	*)			JITVM=no	;;
    esac
    # if should default to no
    if test "x$DEBUG" = xmudflap; then
	JITVM=no
    fi
fi

if test "x$JITVM" != "xno"; then
    # Use glibc backtrace() if available
    AC_CHECK_HEADER([execinfo.h],
	[AC_DEFINE([HAVE_EXECINFO_H], 1,
	[Define to 1 if you have the <execinfo.h> header file.])],)
    AC_ARG_ENABLE(disassembler,
		  AS_HELP_STRING([--enable-disassembler],
				 [Enable jit disassembler using binutils]),
		  [DISASSEMBLER=$enableval], [DISASSEMBLER=auto])
    if test "x$DISASSEMBLER" != "xno"; then
	# FIXME need to check for libiberty first or will fail to link
	AC_CHECK_LIB(iberty, htab_try_create, ,
		     [HAVE_IBERTY="no"])
	AC_CHECK_LIB(bfd, bfd_init, ,
		     [HAVE_BFD="no"])
	AC_CHECK_LIB(opcodes, init_disassemble_info, ,
		     [HAVE_OPCODES="no"])
	if test "x$HAVE_IBERTY"  = "xno" -o \
		"x$HAVE_BFD"	 = "xno" -o \
		"x$HAVE_OPCODES" = "xno"; then
	    if test "x$DISASSEMBLER" != "xauto"; then
		AC_MSG_ERROR([binutils not found, see http://www.gnu.org/software/binutils/])
	    else
		AC_MSG_WARN([binutils not found, see http://www.gnu.org/software/binutils/])
		DISASSEMBLER="no"
	    fi
	fi
    fi
fi
AM_CONDITIONAL(WITH_JITVM, [test "x$JITVM" != "xno"])
if test "x$JITVM" != "xno"; then
    EXL_CFLAGS="$EXL_CFLAGS -DJITVM=1"
    if test "x$DISASSEMBLER" != "xno"; then
	EXL_CFLAGS="$EXL_CFLAGS -DDISASSEMBLER=1"
    fi
fi

dnl Basic tests for the "prototype" builtin module to interface X11
AC_ARG_ENABLE(xwindow,
	      AS_HELP_STRING([--enable-xwindow],
			     [Enable sample X Window interface]),
	      [XWINDOW=$enableval], [XWINDOW=auto])
if test "x$XWINDOW" != "xno"; then
    AC_CHECK_LIB(X11, XOpenDisplay, , [HAVE_XOPENDISPLAY="no"])
    if test "x$HAVE_XOPENDISPLAY" = "xno"; then
	if test "x$XWINDOW" != "xauto"; then
	    AC_MSG_ERROR([X11 not found, see http://www.x.org/])
	fi
    else
	AC_CHECK_LIB(Xft, XftDrawCreate, , [HAVE_XFTDRAWCREATE="no"])
	if test "x$HAVE_XFTDRAWCREATE" = "xno" -a "x$XWINDOW" != "xauto"; then
	    AC_MSG_ERROR([Xft not found, see http://www.x.org/])
	fi
    fi
    if test "x$HAVE_XOPENDISPLAY"  = "xno" -o \
	    "x$HAVE_XFTDRAWCREATE" = "xno"; then
	XWINDOW="no"
    else
	XFT_CFLAGS=`pkg-config xft --cflags`
    fi
fi
AM_CONDITIONAL(WITH_XWINDOW, [test "x$XWINDOW" != "xno"])
if test "x$XWINDOW" != "xno"; then
    EXL_CFLAGS="$EXL_CFLAGS -DXWINDOW=1 $XFT_CFLAGS"
fi

WARN_CFLAGS=""
VISIBILITY_FLAGS=""
if test "x$GCC" = "xyes"; then
    WARN_CFLAGS="\
-Wall \
-Wbad-function-cast \
-Wdeclaration-after-statement \
-Wmissing-prototypes \
-Wmissing-declarations \
-Wnested-externs \
-fno-strict-aliasing \
-Wold-style-definition \
-Wpointer-arith \
-Wstrict-prototypes"
    if test "x$DEBUG" != xmudflap; then
	VISIBILITY_FLAGS="-fvisibility=hidden"
    fi
fi
AC_SUBST([WARN_CFLAGS])

AC_ARG_WITH(simd, AS_HELP_STRING([--with-simd=TYPE],
	[Enable simd instructions (default: sse2 for i686 and x86_64)]),
	[SIMD_TYPE=$withval], [SIMD_TYPE=auto])

EXL_INC='-I$(top_srcdir)/include'
EXL_CFLAGS="$EXL_CFLAGS -std=c99 $VISIBILITY_FLAGS -D_BSD_SOURCE=1 -D_GNU_SOURCE=1 $EXL_INC"
if test "x$DEBUG" != xmudflap; then
    if test "x$SIMD_TYPE" = xauto -o "x$SIMD_TYPE" = xyes; then
	case "$host_cpu" in
	    i686|x86_64)SIMD_TYPE=sse2  ;;
	    *)		SIMD_TYPE=no    ;;
	esac
    fi
else
    SIMD_TYPE=no
fi

if test "x$SIMD_TYPE" != xno; then
    EXL_CFLAGS="$EXL_CFLAGS -m$SIMD_TYPE"
    AC_DEFINE([HAVE_SIMD], 1, [Define to 1 if enabling simd instructions])
    AC_CHECK_FUNC(posix_memalign, [],
	[AC_MSG_ERROR([need posix_memalign when enabling simd instructions])])
fi
AC_SUBST([EXL_CFLAGS])

EXL_LIBS='$(top_builddir)/lib/libexl.la'
AC_SUBST([EXL_LIBS])

AC_OUTPUT([Makefile
	   check/Makefile
	   include/Makefile
	   lib/Makefile
	  ])
